﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Threading;
using JKF.BusinessLayer.BLL;
using JKF.Entities.Model;
using JKF.Substructure;
/*
 1.短信表状态描述
 State: 
    0:未发送;
    1:发送中；
    2.发送成功；
    3：发送失败,记录失败原因。Retry_Times++;Retry_Times
 2.Sms_send_log 添加列 Retry_times int default 0--用于记录失败重试次数；>10次失败则不发送...
 3.获取短信表中：state=0 and (state=3 and Retry_times<11) order by DATE_CREATE asc
 */

namespace JKF.Web
{
    public class Scheduler
    {
        #region Manager
        private static bllSMS_ACCOUNT AccountMgr = new bllSMS_ACCOUNT();
        private static bllSMS_SEND_LOG SMS2SendMgr = new bllSMS_SEND_LOG();
        #endregion

        #region Fields
        public static int Counter = 60;//定时器时间(单位:秒)
        public static int tryTime = 0;
        public static int LoadSmsAccountCounter = 0;
        private static bool HasTask = true;//是否有任务
        private static Dictionary<string, SmsAccount> SysAccount = new Dictionary<string, SmsAccount>();//System sms send task accounts
        #endregion

        #region Methords
        /// <summary>
        /// 获得时间段
        /// </summary>
        /// <param name="bExists"></param>
        /// <param name="max"></param>
        public static void GetInterval(bool bExists, int max)
        {
            if (!bExists)
            {
                if (Counter >= max)
                    Counter = max;
                else
                {
                    //6~22 时段间隔1min执行，其他时段间隔执行
                    if (DateTime.Now.Hour < 6 && DateTime.Now.Hour > 22)
                    {
                        tryTime = tryTime % 20;
                        if (0 == tryTime)
                            Counter *= 2;
                        tryTime += 1;
                    }
                }
                return;
            }
            Counter = 60;
        }
        #endregion

        /// <summary>
        /// 执行注册的任务
        /// </summary>
        public static void Run()
        {
            LoadSmsAccountCounter++;
            LoadSmsAccountCounter %= 8;//Run 8 times reload sms_account
            if (LoadSmsAccountCounter == 0)
            {
                LoadSmsAccounts();
                UpdateSmsAccountLeft();//更新剩余条数
            }
            if (HasTask) SMSSendTask();
            ResetRunTask();
        }

        #region Schedules
        /// <summary>
        /// 短信后台
        /// </summary>
        private static void SMSSendTask()
        {
            if (SysAccount.Count == 0) LoadSmsAccounts();
            if (SysAccount.Count == 0)
            {
                //if no sms account confied return
                AppLogger.Log("SmsSendTask", new Exception("No sms_account found in database,sms send task will skip."));
                return;
            }
            //get sms2 send
            var sms2Send = bllSMS_SEND_LOG.GetSms2Send();
            SmsAccount account;
            foreach (var sms in sms2Send)
            {
                if (!string.IsNullOrEmpty(sms.SHOP_CODE) && SysAccount.ContainsKey(sms.SHOP_CODE))
                {
                    account = SysAccount[sms.SHOP_CODE];
                    try
                    {
                        if (account.NumLeft > 0)
                        {
                            var rslt = SMSHelper.SendSms2Provider(sms.MOBILE, sms.CONTENT, account.Account,
                                                                  account.Password);
                            if (rslt.v_return == 0)
                            {
                                bllSMS_SEND_LOG.SendSmsCallBack(sms.ID, "2", rslt.tt_msgs, "发送成功.");
                            }
                            else
                            {
                                bllSMS_SEND_LOG.SendSmsCallBack(sms.ID, "3", 1, rslt.Info);
                            }
                        }
                        else
                        {
                            bllSMS_SEND_LOG.SendSmsCallBack(sms.ID, "3", 1, "短信账户余额不足，发送失败.请及时充值.");
                        }
                    }
                    catch (Exception exp)
                    {
                        bllSMS_SEND_LOG.SendSmsCallBack(sms.ID, "3", 1, exp.Message);
                    }

                }
                else
                {
                    bllSMS_SEND_LOG.SendSmsCallBack(sms.ID, "3", 1, string.Format("没有找到店铺编号为\"{0}\"短信账户的配置信息.", sms.SHOP_CODE ?? ""));
                }
            }
        }

        /// <summary>
        /// 更新短信账户表剩余短信条目
        /// </summary>
        private static void UpdateSmsAccountLeft()
        {
            var smsDicAccount = new bllSMS_DIC_ACCOUNT();
            var accounts = smsDicAccount.GetListArray("");
            foreach (var accountInfo in accounts)
            {
                try
                {
                    var rslt = SMSHelper.GetSmsProviderInfo(accountInfo.ACCOUNT, accountInfo.PWD);
                    accountInfo.NUM_LEFT = rslt.RICHES;
                    accountInfo.DATE_UPDATE = DateTime.Now;
                    smsDicAccount.Update(accountInfo);
                }
                catch (Exception exp)
                {
                    //AppLogger.Log("UpdateSmsAccountLeft", exp);
                }
            }
        }

        /// <summary>
        /// 重置是否执行任务
        /// </summary>
        public static void ResetRunTask()
        {
            var bhastsk = bllSMS_SEND_LOG.HasSms2Send();
            if (!bhastsk)
            {
                GetInterval(false, 480);//没有任务，开始设定时间间隔
                AppLogger.Log("No Task", new Exception(string.Format("Interval:{0}, TryTimes:{1}", Counter, tryTime)));
            }
            else
            {
                GetInterval(true, 480);//有任务，按照常规设定时间间隔
            }
        }
        #endregion

        #region GlobalFileds
        /// <summary>
        /// 加载短信帐号信息
        /// </summary>
        public static void LoadSmsAccounts()
        {
            SysAccount.Clear();
            var accounts = AccountMgr.GetListArray("STATUS='1'");
            foreach (var account in accounts)
            {
                SysAccount.Add(account.SHOP_CODE, new SmsAccount() { Id = account.ID, Account = account.SMS_ACCOUNT, Password = account.SMS_PWD, NumLeft = account.NUM_LEFT });
            }
        }

        #endregion

        #region Internal Class
        public class SmsAccount
        {
            public Guid Id;
            public string Account;
            public string Password;
            public int NumLeft;
        }
        #endregion
    }
}
